<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app"></div>

    <script>
      // 源码实现部分 -----------------------------------------------------------
      // 进行reactive缓存
      const reactiveMap = new WeakMap()
      const isObject = (target) => target && typeof target === 'object'
      const ReactiveFlags = {
        IS_REACTIVE: '__v_isReactive'
      }

      const reactiveImpl = (target) => {
        if (!isObject(target)) {
          console.warn(`${target} need is object`)
          return
        }

        // 如果传递的是源对象，源对象被代理过后，直接返回代理后的对象
        // 这个缓存是 当target是代理前对象时
        const existingProxy = reactiveMap.get(target)
        if (existingProxy) return existingProxy

        // 这个缓存时 当target是代理后对象时
        if (target && target[ReactiveFlags.IS_REACTIVE]) return target

        const proxy = new Proxy(target, {
          get: (target, key, receiver) => {
            if (key === ReactiveFlags.IS_REACTIVE) return true

            const res = Reflect.get(target, key, receiver)
            // 如果是对象，继续代理，然后返回
            return isObject(res) ? reactive(res) : res
          },
          set: (target, key, value, receiver) => {
            Reflect.set(target, key, value, receiver)
          }
        })
        reactiveMap.set(target, proxy)
        return proxy
      }

      const Vue = { reactive: reactiveImpl }

      // 使用部分 -------------------------------------------------------------------
      const { reactive } = Vue
      const target = {
        name: 'lixx',
        age: 27
      }
      const state = reactive(target)
      const state1 = reactive(target)
      const state2 = reactive(state1)
      console.log(state === state1, state1 === state2) // true true

      document.getElementById('app').innerHTML = `我的名字是：${state.name}, 我${state.age}岁了`
    </script>
  </body>
</html>
